<?php
declare(strict_types=1);

function arrayToString(array $data):string
{
    if(empty($data)){
        return '[]';
    }
    $str = var_export($data,true);
    $str = preg_replace('/\b(\d+)\s*=>/', '', $str);
    $str = preg_replace('/\s+/', '', $str);
    $str = str_replace(',)',']',$str);
    $str = str_replace(')',']',$str);
    $str = str_replace('array(','[',$str);
    return trim($str);
}


function filter_unique(array $array): array
{
    return array_values(array_unique($array));
}

function array_filter_empty_unique(array $array,string|int $k): array
{
    return filter_unique(array_filter($array, function ($v) use ($k) {
        return !empty($v[$k]);
    }));
}


function xn_in_array(mixed $value,array $array, bool $strict = false): bool
{
    return in_array($value, $array, $strict);
}

function array_value(array $arr,string|int $key,string $default = ''):mixed
{
    return $arr[$key] ?? $default;
}

function array_filter_empty(array $arr): array
{
    return array_filter($arr, function ($v) {
        return !empty($v);
    });
}

/*{
    foreach ($arr as $k => $v) {
        if (empty($v)) unset($arr[$k]);
    }
    return $arr;
}*/

// 从一个二维数组中对某一列求和
function arrlist_sum(array $arrlist,string|int $key): int
{
    $n = 0;
    foreach ($arrlist as $arr) {
        $n += $arr[$key];
    }
    return $n;
}


function array_addslashes(array &$var): array
{
    if (is_array($var)) {
        foreach ($var as $k => $v) {
            $var[$k] = array_addslashes($v);
        }
    } else {
        $var = addslashes($var);
    }
    return $var;
}

function array_stripslashes(array &$var): array
{
    if (is_array($var)) {
        foreach ($var as $k => $v) {
            $var[$k] = array_stripslashes($v);
        }
    } else {
        $var = stripslashes($var);
    }
    return $var;
}


/**
 * 多字段排序
 *
 * @return mixed|null
 * @throws Exception
 *
 *
 * $_order = [];
 * foreach ($order as $k => $v){
 * $_order[]=$k;
 * $_order[]=($v==-1?SORT_DESC:SORT_ASC);
 * }
 * $list = arrlist_sort_by_many_field($_list,...$_order);
 */
//$arr = arrlist_sort_by_many_field($array1,'id',SORT_ASC,'name',SORT_ASC,'age',SORT_DESC);
function arrlist_sort_by_many_field(): ?array
{
    $args = func_get_args();

    if (empty($args)) {
        return null;
    }
    $arr = array_shift($args);
    if (!is_array($arr)) {
        return null;
    }
    foreach ($args as $key => $field) {
        if (is_string($field)) {
            $temp = [];
            foreach ($arr as $index => $val) {
                $temp[$index] = $val[$field];
            }
            $args[$key] = $temp;
        }
    }
    $args[] = &$arr;//引用值
    call_user_func_array('array_multisort', $args);
    return array_pop($args);
}

function array_htmlspecialchars(array &$var): array
{
    if (is_array($var)) {
        foreach ($var as $k => $v) {
            $var[$k] = array_htmlspecialchars($v);
        }
    } else {
        $var = str_replace([
            '&',
            '"',
            '<',
            '>',
        ], [
            '&amp;',
            '&quot;',
            '&lt;',
            '&gt;',
        ], $var);
    }

    return $var;
}

function array_trim(array|string &$var): array|string
{
    if (is_array($var)) {
        foreach ($var as $k => $v) {
            $var[$k] = array_trim($v);
        }
    } else {
        $var = trim($var);
    }

    return $var;
}

// 比较数组的值，如果不相同则保留，以第一个数组为准
function array_diff_value(array $arr1,array $arr2): array
{
    foreach ($arr1 as $k => $v) {
        if (isset($arr2[$k]) && $arr2[$k] == $v) unset($arr1[$k]);
    }

    return $arr1;
}

/*
    $data = array();
    $data[] = array('volume' => 67, 'edition' => 2);
    $data[] = array('volume' => 86, 'edition' => 1);
    $data[] = array('volume' => 85, 'edition' => 6);
    $data[] = array('volume' => 98, 'edition' => 2);
    $data[] = array('volume' => 86, 'edition' => 6);
    $data[] = array('volume' => 67, 'edition' => 7);
    arrlist_multisort($data, 'edition', TRUE);
*/
// 对多维数组排序
//function arrlist_multisort($arrlist, $col, $asc = true)
//{
//    $colarr = [];
//    foreach ($arrlist as $k => $arr) {
//        $colarr[$k] = $arr[$col];
//    }
//    $asc = $asc ? SORT_ASC : SORT_DESC;
//    array_multisort($colarr, $asc);array_multisort($colarr, $asc, $arrlist);
//    return $arrlist;
//}

function fun_adm_each(array &$array): array|bool
{
    $res = [];
    $key = key($array);
    if ($key !== null) {
        next($array);
        $res[1] = $res['value'] = $array[$key];
        $res[0] = $res['key'] = $key;
    } else {
        $res = false;
    }
    return $res;
}

// 对数组进行查找，排序，筛选
function arraylist_cond_orderby(array $arraylist, array $cond = [], array $order = [], int $page = 1, int $pagesize = 20) : array
{
    $result = [];
    if (empty($arraylist)) return $arraylist;

    // 根据条件，筛选结果
    if ($cond) {
        foreach ($arraylist as $key => $val) {
            $ok = true;
            foreach ($cond as $k => $v) {
                if (!isset($val[$k]) || $val[$k] != $v) {
                    $ok = false;
                    break;
                }
            }
            if ($ok) $result[$key] = $val;
        }
    } else {
        $result = $arraylist;
    }

    if ($order) {
        [$k, $v] = fun_adm_each($order);
        try {
            $result = arrlist_sort_by_many_field($result, $k, $v == 1 ? SORT_DESC : SORT_ASC);
        } catch (Exception $e) {

        }
    }

    $start = ($page - 1) * $pagesize;

    return array_assoc_slice($result, $start, $pagesize);
}

function array_assoc_slice(array $arraylist, int $start, int $length = 0): array
{
    if (isset($arraylist[0])) return array_slice($arraylist, $start, $length);
    $keys = array_keys($arraylist);
    $keys2 = array_slice($keys, $start, $length);
    $result = [];
    foreach ($keys2 as $key) {
        $result[$key] = $arraylist[$key];
    }

    return $result;
}


// 从一个二维数组中取出一个 key=>value 格式的一维数组
function arrlist_key_values(array $arraylist, string|int $key,string|int $value = NULL): array
{
    $return = [];
    if ($key) {
        foreach ($arraylist as $k => $arr) {
            $return[$arr[$key]] = $value ? $arr[$value] : $k;
        }
    } else {
        foreach ($arraylist as $arr) {
            $return[] = $arr[$value];
        }
    }
    return $return;
}


// 从一个二维数组中取出一个 values() 格式的一维数组，某一列key
function arrlist_values(array $arraylist, string|int $key, bool $needUnique=true):array
{
    if (empty($arraylist)) return [];
    if($needUnique){
        return array_unique(array_column($arraylist,$key));
    }else{
        return array_column($arraylist,$key);
    }
}
function arrlist_index(array $arraylist, array $key, bool $needUnique=true):array
{
    if (empty($arraylist)) return [];
    $result = array_map(function ($item) use ($key) {
        return array_intersect_key($item, array_flip($key));},
    $arraylist);
    return array_filter_empty($result);
}

// 将 key 更换为某一列的值，在对多维数组排序后，数字key会丢失，需要此函数
function arrlist_change_key(array $arraylist,string|int $key, $pre = ''): array
{
    $return = [];
    if (empty($arraylist)) return $return;
    foreach ($arraylist as $arr) {
        if (isset($arr[$key])) {
            $return[$pre . '' . $arr[$key]] = $arr;
        }
    }
    return $return;
}

function arraylist_change_key_many(array $arraylist,string|int $key,string $pre = ''): array
{
    $return = [];
    foreach ($arraylist as $arr) {
        $return[$pre . $arr[$key]] = $arr;
    }
    $arr = null;
    return $return;
}

// 根据某一列的值进行 chunk
function arraylist_chunk(array $arraylist,string|int $key): array
{
    $r = [];
    foreach ($arraylist as $arr) {
        !isset($r[$arr[$key]]) and $r[$arr[$key]] = [];
        $r[$arr[$key]][] = $arr;
    }
    $arr = null;
    return $r;
}

// 根据某一列的值进行 push
function arraylist_push(array &$arrlist,string|int $key,mixed $val):array
{
    $r = [];
    foreach ($arrlist as $k => $arr) {
        $r[$k] = $arr;
        if ($k == $key) {
            foreach ($val as $_k => $_v) {
                $r[$_k] = $_v;
            }
        }
    }
    $arrlist = $r;
    return $r;
}

function arrlist_group(array $arraylist, string|int $key, string|int $ckey = ''):array
{
    $r = [];
        if (empty($arraylist)) return $r;
        foreach ($arraylist as $k => $arr) {
            !isset($r[$arr[$key]]) && $r[$arr[$key]] = [];
            if($ckey){
                $r[$arr[$key]][$arr[$ckey]] = $arr;
            }else{
                $r[$arr[$key]][] = $arr;
            }
        }
        unset($arraylist);

    return $r;
}


/**
 * User: zhixiang
 *  Explain:
 *  -  数组到树形,如果子分类ID比在父分类前面可能有问题
 *
 *
 * @param array  $items
 * @param string $id
 * @param string $pid
 * @param string $son
 * @param bool $key
 *
 * @return array
 */

function arraylist_tree(array $items,string $id = 'id',string $pid = 'pid',string $son = 'children',bool $key = false): array
{
    $tree = []; //格式化的树
    $tmpMap = [];  //临时扁平数据

    foreach ($items as $item) {
        $tmpMap[$item[$id]] = $item;
    }

    if (!$key) {
        foreach ($items as $item) {
            if (isset($tmpMap[$item[$pid]])) {
                $tmpMap[$item[$pid]][$son][] = &$tmpMap[$item[$id]];
            } else {
                $tree[] = &$tmpMap[$item[$id]];
            }
        }
    } else {
        foreach ($items as $item) {
            if (isset($tmpMap[$item[$pid]])) {
                $tmpMap[$item[$pid]][$son][$item[$id]] = &$tmpMap[$item[$id]];
            } else {
                $tree[$item[$id]] = &$tmpMap[$item[$id]];
            }
        }
    }
    unset($tmpMap, $items);
    return $tree;
}

/**
 * //所有上级ID数组
 * $arr=[
 * 1=>0,
 * 2=>1,
 * 3=>1,
 * 4=>1,
 * 5=>2,
 * 6=>2,
 * 7=>2,
 * 8=>3,
 * 9=>4,
 * 10=>5,
 * 11=>10,
 * ];
 */
function arraylist_superior(array $arr): array
{
    $map = $arr;
    foreach ($map as $index => $row) {
        !empty($row) && $map[$index] = _arraylist_superior($arr, $row);
    }
    return $map;
}

function _arraylist_superior(array $arr,string|int $id) :array
{
    return array_merge([$id], !empty($arr[$id]) ? _arraylist_superior($arr, $arr[$id]) : []);
}

/**
 * //子ID数组
 * $arr=[
 * 1=>0,
 * 2=>1,
 * 3=>1,
 * 4=>1,
 * 5=>2,
 * 6=>2,
 * 7=>2,
 * 8=>3,
 * 9=>4,
 * 10=>5,
 * 11=>10,
 * ];
 */

function arraylist_son(array $arr):array
{
    $map = [];
    foreach ($arr as $index => $row) {
        !empty($row) && $map[$row][] = $index;
    }
    foreach ($map as $index => $row) {
        !empty($row) && $map[$index] = array_merge($row, _arraylist_son($map, $row));
    }
    return $map;
}

function _arraylist_son(array $arr,array $id_arr):array
{
    $_arr = [];
    foreach ($id_arr as $row) {
        $_arr = !empty($arr[$row]) ? array_merge($_arr, (array)$arr[$row], _arraylist_son($arr, $arr[$row])) : $_arr;
    }
    return $_arr;
}

/**
 * 一维数据数组生成数据树
 *
 * @param array $list 数据列表
 * @param string $id 父ID Key
 * @param string $pid ID Key
 * @param string $son 定义子数据Key
 *
 * @return array
 */
function arr2tree(array $list,string $id = 'id',string $pid = 'pid',string $son = 'sub'): array
{
    [$tree, $map] = [[], []];
    foreach ($list as $item) {
        $map[$item[$id]] = $item;
    }
    foreach ($list as $item) {
        if (isset($item[$pid]) && isset($map[$item[$pid]])) {
            $map[$item[$pid]][$son][] = &$map[$item[$id]];
        } else {
            $tree[] = &$map[$item[$id]];
        }
    }
    unset($map);
    return $tree;
}

/**
 * 一维数据数组生成数据树
 *
 * @param array $list 数据列表
 * @param string $id ID Key
 * @param string $pid 父ID Key
 * @param string $path
 * @param string $ppath
 *
 * @return array
 */
function arr2table(array $list,string $id = 'id',string $pid = 'pid',string $path = 'path',string $ppath = ''):array
{

    $tree = [];
    foreach (arr2tree($list, $id, $pid) as $attr) {
        $attr[$path] = "{$ppath}-{$attr[$id]}";
        $attr['sub'] = $attr['sub'] ?? [];
        $attr['spl'] = str_repeat("&nbsp;&nbsp;&nbsp;├&nbsp;&nbsp;", substr_count($ppath, '-'));
        $sub = $attr['sub'];
        unset($attr['sub']);
        $tree[] = $attr;
        if (!empty($sub)) {
            $tree = array_merge($tree, (array)arr2table($sub, $id, $pid, $path, $attr[$path]));
        }
    }
    return $tree;
}

/**
 * 获取数据树子ID
 *
 * @param array $list 数据列表
 * @param int $id 起始ID
 * @param string $key 子Key
 * @param string $pkey 父Key
 *
 * @return array
 */
function getArrSubIds(array $list,int $id = 0,string $key = 'id',string $pkey = 'pid'):array
{
    $ids = [$id];
    foreach ($list as $vo) {
        if (intval($vo[$pkey]) > 0 && intval($vo[$pkey]) === $id) {
            $ids = array_merge($ids, getArrSubIds($list, intval($vo[$key]), $key, $pkey));
        }
    }
    return $ids;
}


// 从一个二维数组中取出一个 key=>value 格式的一维数组
function arraylist_key_item(array $arraylist,string|int $key):array
{
    $return = array();
    foreach ($arraylist as $arr) {
        if(!isset($arr[$key])){
            continue;
        }
        $return[$arr[$key]] = $arr;
    }
    return $return;
}

/**
 * 改进：过滤数组中指定（删除或保留）的列
 */
function array_columns(array $input,array $column_keys = [],string|int $index_key = null,bool $retention = true):array
{
    $result = [];
    $keys = is_array($column_keys) ? $column_keys : [];
        foreach ($input as $k => $v) {
            // 删除或保留指定列
            if ($keys) {
                $tmp = array_filter($v, function ($key) use ($column_keys, $retention) {
                    $key_in_array = in_array($key, $column_keys);
                    return $retention ? $key_in_array : !$key_in_array;
                }, ARRAY_FILTER_USE_KEY);
            } else {
                $tmp = $v;
            }

            // 指定索引列
            if (isset($index_key)) {
                $result[$v[$index_key]] = $tmp;
            } else {
                $result[] = $tmp;
            }
        }

    return $result;
}
?>